package driver

import (
	"fmt"
	"gitee.com/xluomo945/fm/helper"
	"gitee.com/xluomo945/fm/setting"
	"github.com/gin-gonic/gin"
	syslog "log"
	"os"
	"sync"
	"time"
)

type fileWriter struct {
	config      setting.LoggerConfig
	current     string
	writer      *os.File
	isShowTrace bool
}

func (w *fileWriter) OpenTrace() {
	w.isShowTrace = true
}

func (w *fileWriter) Info(ctx *gin.Context, msg string) {
	w.write(ctx, "INFO", msg)
}

func (w *fileWriter) Warn(ctx *gin.Context, msg string) {
	w.write(ctx, "WARN", msg)
}

func (w *fileWriter) Fail(ctx *gin.Context, msg string) {
	w.write(ctx, "FAIL", msg)
}

func (w *fileWriter) Custom(ctx *gin.Context, flag string, msg string) {
	w.write(ctx, flag, msg)
}

func (w *fileWriter) write(ctx *gin.Context, flag string, msg string) {
	w.isUpdateWriter()
	w.console(ctx, flag, msg)
	mu := sync.Mutex{}
	mu.Lock()
	defer mu.Unlock()
	if w.isShowTrace {
		_, _ = w.writer.WriteString(fmt.Sprintf("%s [%s]: [%s] %s", time.Now().Format("2006-01-02 15:04:05"), trace(ctx), flag, msg))
	} else {
		_, _ = w.writer.WriteString(fmt.Sprintf("%s [%s] %s", time.Now().Format("2006-01-02 15:04:05"), flag, msg))
	}
}

func (w *fileWriter) console(ctx *gin.Context, flag string, msg string) {
	if w.config.PrintConsole {
		if w.isShowTrace {
			syslog.Println(fmt.Sprintf("[%s][%s] %s", trace(ctx), flag, msg))
		} else {
			syslog.Println(fmt.Sprintf("[%s] %s", flag, msg))
		}
	}
}

func (w *fileWriter) isUpdateWriter() {
	if w.config.ByDay {
		current := name(w.config)
		if current != w.current {
			writer, err := createFileWriter(current)
			if err != nil {
				return
			}
			_ = w.writer.Close()
			w.writer = writer
		}
	}
}

func (w *fileWriter) Close() {
	if w.writer != nil {
		_ = w.writer.Close()
	}
}

func FileCreate(config setting.LoggerConfig) (setting.LogWriter, error) {
	if !helper.PathIsExists(config.Dir) {
		return nil, fmt.Errorf("model writer: Config dir is not exists. [%s]", config.Dir)
	}

	if helper.StringEmpty(config.Name) {
		syslog.Println("[Warn] model config name is empty. default name: log")
		config.Name = "log"
	}

	current := name(config)
	writer, err := createFileWriter(current)
	if err != nil {
		return nil, err
	}

	return &fileWriter{current: current, config: config, writer: writer}, nil
}

func createFileWriter(name string) (*os.File, error) {
	return os.OpenFile(name, os.O_CREATE|os.O_WRONLY, 0666)
}
